home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-30 | 16.2 KB | 601 lines | [TEXT/CWIE] |
- /*
- File: CWindows.cp
-
- Contains: Layer built on top of the Window Manager
-
- Written by: Arno Gourdol
-
- Copyright: © 1994-1996 by Apple Computer, Inc., all rights reserved.
-
-
- */
-
- #include "CWindows.h"
-
- #include <LowMem.h> // for LMGetGrayRgn()
- #include <Memory.h>
- #include <Script.h>
- #include <ToolUtils.h>
- #include <Sound.h>
-
- #include "CFonts.h"
- #include "TEnvironment.h"
- #include "macros.h"
- #include "assert.h"
-
-
-
- CWindow *CWindow::gWindowList = NULL;
-
-
-
- // --------------------------------------------------------------------
- // CWindow
- // --------------------------------------------------------------------
- // Constructor
-
- CWindow::CWindow(UInt16 windowType) :
- fWindow(NULL),
- fNextWindow(NULL),
- fWindowType(windowType)
- {
- // Prepend this to the list of windows
- this->SetNextWindow(gWindowList);
- gWindowList = this;
- }
-
-
-
- // --------------------------------------------------------------------
- // CWindow
- // --------------------------------------------------------------------
- // Destructor
-
- CWindow::~CWindow(void)
- {
- if (GetWindowRef() != NULL)
- Close();
-
- // Remove this from the list of windows
- if (gWindowList == this)
- {
- gWindowList = GetNextWindow();
- }
- else if (gWindowList != NULL)
- {
- for (CWindow *window = gWindowList; window != NULL; window = window->GetNextWindow())
- {
- if (window->GetNextWindow() == this)
- {
- window->SetNextWindow(this->GetNextWindow());
- break;
- }
- }
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // CloseRequested
- // --------------------------------------------------------------------
- // Hook function called before a window gets closed
- // An opportunity to ask the user to confirm the operation
- // Returns true if must go ahead.
-
- Boolean CWindow::CloseRequested(void)
- {
- return true;
- }
-
-
-
- // --------------------------------------------------------------------
- // Close
- // --------------------------------------------------------------------
- // Close the window without asking the user for confirmation
- // Call Close after CloseRequested() has returned true
-
- void CWindow::Close(void)
- {
- assert(GetWindowRef() != NULL);
- DisposeWindow(GetWindowRef());
- fWindow = NULL;
- }
-
-
-
- // --------------------------------------------------------------------
- // MenusWillShow
- // --------------------------------------------------------------------
- // Hook function called before the menus are going to be displayed
- // (after the user has clicked on them).
- // Enable/disable items appropriately
-
- void CWindow::MenusWillShow(void)
- {
-
- }
-
-
-
- // --------------------------------------------------------------------
- // WindowActivated
- // --------------------------------------------------------------------
- // Hook function called when the window activation state changes
-
- void CWindow::WindowActivated(Boolean active)
- {
- #pragma unused(active)
-
- }
-
-
-
- // --------------------------------------------------------------------
- // GetCWindow
- // --------------------------------------------------------------------
- // Return a CWindow object from a Toolbox window
- // Returns NULL if there is no CWindow object associated with this window
-
- CWindow* CWindow::GetCWindow(WindowRef window)
- {
- // ??? Try to write this as a friend conversion operator
- CWindow* result;
- for (result = gWindowList; result != NULL; result = result->GetNextWindow())
- {
- if (result->GetWindowRef() == window)
- break;
- }
- return result;
- }
-
-
-
- // --------------------------------------------------------------------
- // Pulse
- // --------------------------------------------------------------------
- // Hook function called regularly
-
- void CWindow::Pulse(void)
- {
- // nothing to do in superclass
- }
-
-
-
- // --------------------------------------------------------------------
- // ResizeBy
- // --------------------------------------------------------------------
- // Function to resize a window to the indicated relative dimensions
-
- void CWindow::ResizeBy(GraphicalUnit dx, GraphicalUnit dy)
- {
- #pragma unused(dx, dy)
- assert(false); // Not implemented yet
- }
-
-
-
- // --------------------------------------------------------------------
- // ResizeTo
- // --------------------------------------------------------------------
- // Function to resize a window to the indicated absolute dimensions
-
- void CWindow::ResizeTo(GraphicalUnit width, GraphicalUnit height)
- {
- SizeWindow(fWindow, width, height, true);
-
- SetPort(GetGrafPtr());
- CRect windowRect = GetGrafPtr()->portRect; // Use Frame() ???
-
- ClipRect(windowRect);
- EraseRect(windowRect);
- InvalRect(windowRect); // Update content of window later
- }
-
-
-
- // --------------------------------------------------------------------
- // Zoom
- // --------------------------------------------------------------------
- // Function called to change the zoomed state of a window
-
- void CWindow::Zoom(Boolean zoomOut)
- {
- CRect newWindowRect;
- CRect monitorRect;
-
- TDrawContext drawContext(GetGrafPtr()); // ZoomWindow requires the port to be set
- if (drawContext.Lock())
- {
- {
- TEnvironment environment;
- environment.GetMonitorRect(Bounds(), monitorRect); // Get the rectangle of the best monitor
- }
- monitorRect.SetTop(monitorRect.Top() + (LMGetMBarHeight() - 3)); // Make room for the title bar (assuming same as menu bar)
- monitorRect.InsetBy(4); // Give some edge to the window
-
- if (zoomOut)
- {
- assert(fExtent.Right() > 10);
- assert(fExtent.Bottom() > 10);
-
- // Calculate where the new window would be if we didn't move it
- newWindowRect = Bounds();
- newWindowRect.SetWidth(fExtent.Right());
- newWindowRect.SetHeight(fExtent.Bottom());
-
- if (!monitorRect.Contains(newWindowRect))
- {
- newWindowRect.OffsetBy(monitorRect.Left() - newWindowRect.Left(), monitorRect.Top() - newWindowRect.Top());
- newWindowRect.SetRight(min(newWindowRect.Right(), monitorRect.Right()));
- newWindowRect.SetBottom(min(newWindowRect.Bottom(), monitorRect.Bottom()));
- }
-
- assert(!newWindowRect.IsEmpty());
- SetWindowStandardState(fWindow, newWindowRect); // new zoom-out rect
- }
- else
- {
- // Adjust the user state to minimize moving
- GetWindowUserState(fWindow, newWindowRect);
-
- newWindowRect.OffsetBy(Bounds().Left() - newWindowRect.Left(), Bounds().Top() - newWindowRect.Top());
- newWindowRect.SetRight(min(newWindowRect.Right(), monitorRect.Right()));
- newWindowRect.SetBottom(min(newWindowRect.Bottom(), monitorRect.Bottom()));
- SetWindowStandardState(fWindow, newWindowRect);
- }
-
- ClipRect(Bounds());// White out contents of window
- EraseRect(Bounds());
- ZoomWindow(fWindow, inZoomOut, false); // Always zoom on the stdState
-
- InvalRect(Bounds());
- drawContext.Unlock();
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // MakeWindow
- // --------------------------------------------------------------------
- // Function called to construct a Toolbox window for this object
- // Can only be called once.
-
- WindowRef CWindow::MakeWindow(void)
- {
- assert(GetWindowRef() == NULL);
- WindowRef aNewWindow = GetNewCWindow(128, NULL, WindowRef(-1)); // (-)
-
- return aNewWindow;
- }
-
-
-
- // --------------------------------------------------------------------
- // Show
- // --------------------------------------------------------------------
- // Function called to show the window if it was invisible
- // Creates the window if it did not exist
-
- void CWindow::Show(void)
- {
- if (GetWindowRef() == NULL)
- CreateWindow();
-
- ::ShowWindow(GetWindowRef());
- }
-
-
-
- // --------------------------------------------------------------------
- // Hide
- // --------------------------------------------------------------------
- // Function called to hide the window
- // The window must have been create previouslt
-
- void CWindow::Hide(void)
- {
- assert(GetWindowRef() != NULL);
- ::HideWindow(GetWindowRef());
- }
-
-
-
- // --------------------------------------------------------------------
- // FilterEvent
- // --------------------------------------------------------------------
- // Hook functionc called before an event gets processed
- // Returns true if the event was handled.
- // It calls FilterKey
-
- Boolean CWindow::FilterEvent(const EventRecord& event)
- {
- Boolean result = false; // Event not handled
-
- if (event.what == keyDown || event.what == autoKey)
- {
- UInt16 key;
- UInt16 keyCode = event.message & keyCodeMask;;
- UInt16 keyASCII = event.message & charCodeMask;
-
- if (keyASCII == 0x10)
- {
- // It's a function key
- key = keyCode;
- }
- else if (keyCode == 0x01)
- {
- // The ESC and Clear keys return the same ASCII code
- // To differentiate them, we need to look at the keycode
- // as well. If it's 1, it's the ESC key.
- key = keyEscape;
- }
- else
- {
- key = keyASCII;
- }
- result = FilterKey(event, key);
- }
- return result;
- }
-
-
-
- // --------------------------------------------------------------------
- // MouseDown
- // --------------------------------------------------------------------
- // Hook function called when the content of the window has been clicked
-
- void CWindow::MouseDown(const EventRecord& event)
- {
- #pragma unused(event)
- }
-
-
-
- // --------------------------------------------------------------------
- // FilterKey
- // --------------------------------------------------------------------
- // Constructor
-
- Boolean CWindow::FilterKey(const EventRecord& event, UInt16 key)
- // Hook function called before key events are processed
- // Returns true if the event was handled.
- {
- #pragma unused(event)
- #pragma unused(key)
- return false; // Event not handled
- }
-
-
-
- // --------------------------------------------------------------------
- // MoveTo
- // --------------------------------------------------------------------
- // Function to change the location of the window
-
- void CWindow::MoveTo(const CPoint& location)
- {
- assert(GetWindowRef() != NULL);
-
- MoveWindow(GetWindowRef(), location.X(), location.Y(), false);
-
- FrameMoved(location);
- }
-
-
-
- // --------------------------------------------------------------------
- // FrameResized
- // --------------------------------------------------------------------
- // Hook function called when the window has been resized
-
- void CWindow::FrameResized(GraphicalUnit newWidth, GraphicalUnit newHeight)
- {
- #pragma unused(newWidth, newHeight)
- }
-
-
-
- // --------------------------------------------------------------------
- // FrameMoved
- // --------------------------------------------------------------------
- // Hook function called when the window location has changed
-
- void CWindow::FrameMoved(const CPoint& newLocation)
- {
- #pragma unused(newLocation)
-
- }
-
-
-
- // --------------------------------------------------------------------
- // ForceOnScreen
- // --------------------------------------------------------------------
- // Function that ensures that the window is visible on screen
-
- void CWindow::ForceOnScreen(void)
- {
- #if 1
- enum { kMinDragArea = 4 };
-
- CTempRgn theDragRgn;
- WindowRecord & theWindowRecord = *((WindowPeek)GetWindowRef());
- DiffRgn(theWindowRecord.strucRgn, theWindowRecord.contRgn, theDragRgn);// strucRgn less contRgn ≈≈ drag rgn
- if (EmptyRgn(theDragRgn))
- CopyRgn(theWindowRecord.strucRgn, theDragRgn);// at least get the strucRgn
-
- CPoint contentRegionInset = CPoint((*theWindowRecord.contRgn)->rgnBBox.left, (*theWindowRecord.contRgn)->rgnBBox.top)
- - CPoint((*theWindowRecord.strucRgn)->rgnBBox.left, (*theWindowRecord.strucRgn)->rgnBBox.top);
-
- // get the desktop rgn, inset by a minimal drag area
- CTempRgn theSectRgn(LMGetGrayRgn());
- InsetRgn(theSectRgn, kMinDragArea, kMinDragArea); // inset theSectRgn
- SectRgn(theDragRgn, theSectRgn, theSectRgn); // do drag rgn && desktop rgn instersect ?
-
- if (EmptyRgn(theSectRgn))
- {
- GraphicalUnit deltaX;
- GraphicalUnit deltaY;
- CRect visScreenRect;
- CRect theFrame(GetWindowRef()->portRect);
-
- // since we don't _really_ know what the drag rgn is, we'll assume that moving the
- // topleft pt of the window on screen is sufficient to make it draggable, so calculate
- // the deltas necessary to move the topleft pt into visible screen CRect.
-
- this->GetMaxIntersectedDevice(visScreenRect);
- visScreenRect.InsetBy(kMinDragArea);
-
- if (theFrame.Top() < visScreenRect.Top())
- deltaY = (visScreenRect.Top() - theFrame.Top() + contentRegionInset.Y());
- else if (theFrame.Top() > visScreenRect.Bottom())
- deltaY = (visScreenRect.Bottom() - theFrame.Top() - contentRegionInset.Y());
-
- if (theFrame.Left() < visScreenRect.Left())
- deltaX = (visScreenRect.Left() - theFrame.Left() + contentRegionInset.X());
- else if (theFrame.Left() > visScreenRect.Right())
- deltaX = (visScreenRect.Right() - theFrame.Right() - contentRegionInset.X());
-
- this->MoveTo(CPoint(theFrame.Left() + deltaX, theFrame.Top() + deltaY));
- }
- #else
- // This routine has been promoted into the API, but not documented.
- // I hope this is a correct interpretation of what it does!
- CheckWindowPosition(GetDialogWindow(fDlog), ccDragBar, false);
- #endif
- }
-
-
-
- // --------------------------------------------------------------------
- // GetMaxIntersectedDevice
- // --------------------------------------------------------------------
- // Returns the device that intersects most of the specified rectangle
-
- GDHandle CWindow::GetMaxIntersectedDevice(CRect& screenRect)
- {
- long maxSectArea = 0;
- CTempRgn structure;
- GetWindowStructureRgn(GetWindowRef(), structure);
- Rect globalStrucRect = (*structure)->rgnBBox;
-
- GDHandle aGDHandle = GetDeviceList();
- GDHandle maxSectGD = GetMainDevice(); // set as best choice default
- while (aGDHandle)
- { // calc which scrn intersects largest part of window
- if (TestDeviceAttribute(aGDHandle, screenDevice) && TestDeviceAttribute(aGDHandle, screenActive))
- {
- Rect aGDScreenRect = (*aGDHandle)->gdRect;
- CRect gdSectRect;
-
- if (SectRect(&globalStrucRect, &aGDScreenRect, gdSectRect))
- {
- long sectArea = gdSectRect.Width() * gdSectRect.Height();
- if (sectArea > maxSectArea) // do we have a new winner?
- {
- maxSectArea = sectArea;
- maxSectGD = aGDHandle;
- }
- }
- }
- aGDHandle = GetNextDevice(aGDHandle);
- }
-
- if (maxSectGD != GetMainDevice())
- screenRect = (*maxSectGD)->gdRect;
- else
- { // Account for menu bar on the main screen.
- // Don't just assume that it's at the top of
- // the screen!
- CTempRgn tempRgn;
- Rect gdRect = (*maxSectGD)->gdRect;
-
- RectRgn(tempRgn, &gdRect); // main screen with menubar
- SectRgn(tempRgn, LMGetGrayRgn(), tempRgn); // GetGrayRgn == desktop rgn w/o menubar
- screenRect = (*(RgnHandle) tempRgn)->rgnBBox; // => main screen w/o menubar
- }
- return maxSectGD;
- }
-
-
-
- // --------------------------------------------------------------------
- // DrawDispatch
- // --------------------------------------------------------------------
- // Callback function that dispatch to the draw method
-
- pascal void CWindow::DrawDispatch(short depth, short deviceFlags,
- GDHandle targetDevice, CWindow* window)
- {
- #pragma unused(targetDevice)
- // Clip to the visible region
- SetClip(window->GetGrafPtr()->visRgn);
-
- Boolean isColor = ((deviceFlags & (1L << gdDevType)) == 0);
- TDrawContext drawContext(window->GetGrafPtr(), depth, isColor);
- if (drawContext.Lock())
- {
- window->Draw(drawContext);
- drawContext.Unlock();
- }
- }
-
-
-
- // --------------------------------------------------------------------
- // DoUpdate
- // --------------------------------------------------------------------
- // Function that processes all the update events, calling the Draw()
- // method as appropriate
-
- void CWindow::DoUpdate(RgnHandle area)
- {
- // Set a "normal" graphic env.
- SetPort(GetGrafPtr());
- PenNormal();
- //ForeColor(blackColor);
- //BackColor(whiteColor);
-
- // Loop thru all the devices and call the DrawDispatch proc each time
- {
- DeviceLoopDrawingUPP upp = NewDeviceLoopDrawingProc(DrawDispatch);
-
- DeviceLoop(area, upp, (long)this, (DeviceLoopFlags)0);
-
- DisposeRoutineDescriptor(upp);
- }
-
- ClipRect(&GetGrafPtr()->portRect); // ??? Use Frame() instead
- }
-
-
-
- // --------------------------------------------------------------------
- // DrawGrowIcon
- // --------------------------------------------------------------------
- // Function that draws the grow icon
-
- void CWindow::DrawGrowIcon(TDrawContext& drawContext) const
- {
- // Draw the grow icon, clipped to only the grow icon
- // (draws annoying outline for scrollbars else)
- CRect growIconRect(drawContext.Bounds());
-
- growIconRect.SetLeftTop(CPoint(growIconRect.Right() - 15, growIconRect.Bottom() - 15));
-
- {
- CRect area((**GetGrafPtr()->visRgn).rgnBBox);
- if (::SectRect(growIconRect, area, growIconRect))
- {
- ::ClipRect(growIconRect);
- ::DrawGrowIcon(GetWindowRef());
- ::SetClip(GetWindowPort(fWindow)->visRgn); // Restore the clip region to the window content
- }
- }
- }
-